package com.caine.web.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.caine.web.entity.Group;
import com.caine.web.entity.Resource;
import com.caine.web.service.IGroupService;
import com.caine.web.service.IResourceService;
import com.caine.web.tool.BeanCopyTool;
import com.caine.web.vo.NetWorkVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.context.request.async.WebAsyncTask;

import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @Author: CaineZhu
 * @Description:
 * @Date: Created in 15:49 2020/12/17
 * @Modified By:
 */
@Slf4j
@RestController
public class TestController {

    @Autowired
    private IGroupService groupService;
    @Autowired
    private IResourceService resourceService;

    @RequestMapping("test")
    public Object test() {
        List<Group> viewCfgIndicatorGroupLst = groupService.list();
        List<Resource> formulaList = resourceService.list();
        List<NetWorkVO> childDataLst = BeanCopyTool.copyListProperties(formulaList, NetWorkVO::new);
        Map<Integer, List<NetWorkVO>> NetWorkVOGroupMap = childDataLst.stream().collect(Collectors.groupingBy(s -> s.getGroupId()));
        List<NetWorkVO> netWorkVOS = loopChild(viewCfgIndicatorGroupLst, 0);
        bindData(netWorkVOS, NetWorkVOGroupMap);
        return netWorkVOS;
    }

    @RequestMapping("test2")
    public void test2(HttpServletRequest request) {
        AsyncContext asyncContext = request.startAsync();
        asyncContext.addListener(new AsyncListener() {
            @Override
            public void onComplete(AsyncEvent asyncEvent) throws IOException {
                log.info(">>>>>>>>>>done.");
            }

            @Override
            public void onTimeout(AsyncEvent asyncEvent) throws IOException {
                log.info(">>>>>>>>>>timeout.");
            }

            @Override
            public void onError(AsyncEvent asyncEvent) throws IOException {
                log.error(">>>>>>>>>>error", asyncEvent.getThrowable());
            }

            @Override
            public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
                log.info(">>>>>>>>>>start.");
            }
        });
        asyncContext.setTimeout(2000L);
        asyncContext.start(new Runnable() {
            @Override
            public void run() {
                log.info(">>>>>>>>>>running.");
            }
        });
    }

    @RequestMapping("test3")
    public WebAsyncTask<String> test3(HttpServletRequest request) {
        log.info("当前主线程：{}", Thread.currentThread().getName());
        Callable<String> callable = () -> {
            log.info("内部线程开始：{}", Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (Exception e) {
                // TODO: handle exception
            }
            log.info("副线程返回");
            log.info("内部线程返回：{}", Thread.currentThread().getName());
            return "success";
        };
        WebAsyncTask<String> webTask = new WebAsyncTask<>(5000L, callable);
        webTask.onTimeout(() -> "超时");
        return webTask;
    }

    ExecutorService executor = Executors.newSingleThreadExecutor();

    @RequestMapping("test4")
    public DeferredResult<String> test4(HttpServletRequest request) {
        System.out.println("外部线程：" + Thread.currentThread().getName());
        //设置超时时间
        DeferredResult<String> result = new DeferredResult<String>(60 * 1000L);
        //处理超时事件 采用委托机制
        result.onTimeout(() -> {
            System.out.println("DeferredResult超时");
            result.setResult("超时了!");
        });
        result.onCompletion(new Runnable() {

            @Override
            public void run() {
                //完成后
                System.out.println("调用完成");
            }
        });
        executor.execute(() -> {
            //处理业务逻辑
            System.out.println("内部线程：" + Thread.currentThread().getName());
            //返回结果
            result.setResult("DeferredResult!!");
        });
        return result;
    }

    /**
     * 菜单层级
     *
     * @param list
     * @param groupId
     * @return
     */
    public List<NetWorkVO> loopChild(List<Group> list, int groupId) {
        List<NetWorkVO> child = new ArrayList<>();
        list.forEach(s -> {
            if (s.getParentGroupId() == groupId) {
                NetWorkVO v = new NetWorkVO();
                v.setGroupName(s.getGroupName());
                v.setGroupId(s.getGroupId());
                v.setParentId(s.getParentGroupId());
                v.setChildList(loopChild(list, s.getGroupId()));
                child.add(v);
            }
        });
        return child;
    }

    /**
     * 菜单数据绑定
     *
     * @param netWorkVOS
     * @param NetWorkVOGroupMap
     */
    public void bindData(List<NetWorkVO> netWorkVOS, Map<Integer, List<NetWorkVO>> NetWorkVOGroupMap) {
        netWorkVOS.forEach(s -> {
            List<NetWorkVO> childList = s.getChildList();
            if (CollectionUtil.isNotEmpty(childList)) {
                bindData(childList, NetWorkVOGroupMap);
            } else {
                s.setChildList(NetWorkVOGroupMap.get(s.getGroupId()));
            }
        });
    }
}
